/*
 * edl.c - 
 * Clunix, cezanne@clunix.com, 2005
 * Clunix, joon626@clunix.com
 *
 * Copyright (c) 2001-2008 by Clunix Inc. All Rights Reserved.
 */

#include "config.h"

#include "edl.h"

srt_t	ST_EDEXPR;

typedef void *yyscan_t;

typedef struct {
	char	*instr;
	int	instr_len;
	int	instr_ptr;
	ecm_uint32	lineno;
} edl_input_t;

int edlparse(yyscan_t scanner, sr_t **, ECMBOOL checkmode, ecm_uint32 *perrlineno, char **perrmsg);
edl_input_t *edlget_extra(yyscan_t scanner);
void edllex_init(yyscan_t *);
void edllex_destroy(yyscan_t);
void edlset_extra(void *, yyscan_t);
void edlset_debug(int, yyscan_t);

void
edl_input(yyscan_t scanner, char *buf, int *presult, int max_size)
{
	int	copycnt;
	edl_input_t	*input = edlget_extra(scanner);
	
	if (input->instr_ptr < 0) {
		*presult = 0;
		return;
	}
	if (input->instr_ptr == input->instr_len) {
		buf[0] = '\n';
		*presult = 1;
		input->instr_ptr = -1;
		return;
	}
	copycnt = input->instr_len - input->instr_ptr;
	if (copycnt > max_size)
		copycnt = max_size;
	memcpy(buf, input->instr + input->instr_ptr, copycnt);
	input->instr_ptr += copycnt;
	*presult = copycnt;
}

#ifdef ECM_DEBUG
ECMBOOL	scanner_debug = ECM_FALSE;
#endif

static ECM_INLINE sr_t *
parse_edexpr(char *buf, ECMBOOL checkmode, ecm_uint32 *perrlineno, char **perrmsg)
{
	sr_t	*sr_edexpr = NULL;
	edl_input_t	input;
	yyscan_t	scanner;
	char		*errmsg;
	ecm_uint32	errlineno;

	edllex_init(&scanner);
	edlset_extra(&input, scanner);
#ifdef ECM_DEBUG
	edlset_debug(scanner_debug, scanner);
#endif
	input.instr = buf;
	input.instr_len = (int)ecm_strlen(buf);
	input.instr_ptr = 0;
	input.lineno = 0;

	errmsg = NULL;
	if (edlparse(scanner, &sr_edexpr, checkmode, &errlineno, &errmsg) != 0) {
		if (perrlineno)
			*perrlineno = errlineno;
		if (perrmsg)
			*perrmsg = errmsg;
		else
			ecm_free(errmsg);
		sr_edexpr = NULL;
	}

	edllex_destroy(scanner);

	return sr_edexpr;
}

void
edl_input_addline(yyscan_t scanner)
{
	edl_input_t	*pinput;

	pinput = edlget_extra(scanner);
	pinput->lineno++;
}

ecm_uint32
edl_input_getline(yyscan_t scanner)
{
	edl_input_t	*pinput;

	pinput = edlget_extra(scanner);
	return pinput->lineno;
}

sr_t *
edl_get_edexpr(const char *edstr, ecm_uint32 *perrlineno, char **perrmsg)
{
	sr_t	*sr_edexpr;
	char	*buf;

	if (edstr == NULL)
		return NULL;
	buf = ecm_strdup(edstr);
	sr_edexpr = parse_edexpr(buf, ECM_FALSE, perrlineno, perrmsg);
	ecm_free(buf);

	return sr_edexpr;
}

ECMBOOL
edl_check_edexpr(const char *edstr, ecm_uint32 *perrlineno, char **perrmsg)
{
	sr_t	*sr_edexpr;
	char	*buf;
	ECMBOOL	res = ECM_FALSE;

	if (edstr == NULL)
		return ECM_FALSE;

	buf = ecm_strdup(edstr);
	sr_edexpr = parse_edexpr(buf, ECM_TRUE, perrlineno, perrmsg);
	ecm_free(buf);

	if (sr_edexpr)
		res = ECM_TRUE;
	sr_free(sr_edexpr);

	return res;
}

ECMBOOL
edl_initialize(void)
{
	static ECMBOOL	initialized;

	if (initialized)
		return ECM_TRUE;
	ST_EDEXPR = sr_type_add(SR_BT_DIR, "edexpr", NULL, NULL);
	initialized = ECM_TRUE;
	return ECM_TRUE;
}
